/**

   Debug.c
   =======

   Helper for debugging

**/



#include <stdio.h>
#include "bitfield.h"
#include "../master/huffman.h"
#include "../master/btree.h"
#include "../master/heap.h"
#include "../master/dc.h"
#include "../master/llist.h"
#include "../master/chunk.h"
#include "../master/file.h"
#include "debug.h"



/**

   Funtion: void debug_print_bnode(struct b_node* t)
   -------------------------------------------------
	
   Print a btree rooted at node `t` in dot (graphviz) format
	
**/

void debug_print_bnode(struct b_node* t, struct huff_tree* h)
{
  uint8_t i,j;
	
  /* Return if NULL */
  if (t == NULL)
    {
      return;
    }

  /* Recurse children */
   for(i=0;i<2*BTREE_DEGREE;i++)
    {
      if (t->children[i] != NULL)
	{
	  /* print current node */
	  printf("\"");
	  for(j=0;j<t->nkeys;j++)
	    {
	      printf(" ");
	      debug_huff_decode(t->keys[j]->name,h);
	    }
	  printf(" \"");

	  /* Arrow */
	  printf(" -> ");

	  /* Print children */
	  printf("\"");
	  for(j=0;j<t->children[i]->nkeys;j++)
	    {
	      printf(" ");
	      debug_huff_decode(t->children[i]->keys[j]->name,h); 
	    }
	  printf(" \" [label=\"%d\"];",i);

	}
      debug_print_bnode(t->children[i],h);
    }
 	
  return;
}


/**

   Funtion: void debug_print_btree(struct b_tree* t)
   -------------------------------------------------
	
   Print a btree in dot (graphviz) format
	
**/

void debug_print_btree(struct b_tree* t, struct huff_tree* h)
{
  debug_print_bnode(t->root,h);
  return;
}



/**

   Funtion: void debug_print_hnode(struct huff_node* t)
   -----------------------------------------------------
	
   Print huffman nodes
	
**/

void debug_print_hnode(struct huff_node* t)
{
  /* Print if leaf */
  if ( (t->left == NULL) && (t->right == NULL) )
    {
      printf("(%u,%0.3f)",(unsigned char)t->c,t->freq);
    }
  else
    {
      /* Print node otherwise */
      debug_print_hnode(t->left);
      debug_print_hnode(t->right);
    }
  return;
}



/**

   Funtion: void debug_print_htree(struct huff_tree* t)
   -----------------------------------------------------
	
   Print a huffman tree
	
**/

void debug_print_htree(struct huff_tree* t)
{
  debug_print_hnode(t->root);
  return;
}



/**

   Function: void debug_print_heap(struct heap* h)
   -----------------------------------------------

   print a heap

**/


void debug_print_heap(struct heap* h)
{
  unsigned int i,j;
  j=0;

  if (!h->n)
    {
      return;
    }

  printf("Digraph heap { ");

  for(i=0;i<h->n;i++)
    {
      if(2*i+1 < h->n)
	{
	  if (h->items[2*i+1] != NULL)
	    {
	      j++;
	      printf("\" ");
	      printf("%s",h->items[i]->ip);
	      printf(" \"");
	      printf(" -> ");
	      printf("\" ");
	      printf("%s",h->items[2*i+1]->ip);
	      printf(" \";");
	    }
	}
      
      if(2*i+2 < h->n)
	{
	  if (h->items[2*i+2] != NULL)
	    {
	      j++;
	      printf("\" ");
	      printf("%s",h->items[i]->ip);
	      printf(" \"");
	      printf(" -> ");
	      printf("\" ");
	      printf("%s",h->items[2*i+2]->ip);
	      printf(" \";");
	    }
	}

    }

  if (!j)
    {
      printf("\" ");
      printf("%s",h->items[0]->ip);
      printf(" \"");
    }

  printf(" }\n");

}



/**

   Function: void debug_print_llist(struct llist* ll)
   --------------------------------------------------

   Print a linked list

**/

void debug_print_llist(struct llist* ll)
{
  struct dc* cursor;
  
  if (ll->head == NULL)
    {
      return;
    }

  cursor = ll->head;
  do
    {
      printf(" %llu ",cursor->id);
      cursor=cursor->next;
    }while(cursor!=ll->head);
  
  printf("\n");
  return;
}



/**

   Funtion: void debug_print_bitfield(struct bitfield* bf)
   -------------------------------------------------------
	
   Print a bitfield
	
**/


void debug_print_bitfield(struct bitfield* bf)
{
  int i;
  
  for(i=0;i<bf->n;i++)
    {
      if ( bf_isset(bf,i) )
	{
	  printf("1");
	}
      else
	{
	  printf("0");
	}
    }
  
  return;
}


/**

   Function: char* debug_huff_decode_helper(struct bitfield* bf, struct huff_node* t)
   ----------------------------------------------------------------------------------

   Decode `bf` via huffman code

**/


char* debug_huff_decode_helper(struct bitfield* bf, struct huff_node* t)
{
  int i;
  struct huff_node* tree;

  tree = t;

  i=0;
  while( i<bf->n )
    {
      /* Branch according to encoding */
      if (bf_isset(bf,i))
	{
	  tree = tree->left;
	}
      else
	{
	  tree = tree->right;
	}
      
      /* Print if leaf */
      if ( (tree->left == NULL) && (tree->right == NULL) )
	{
	  printf("%c",tree->c);
	  tree = t;
	}
      
      i++;
    }

  return NULL;
}


/**

   Function: char* debug_huff_decode(struct bitfield* bf, struct huff_tree* t)
   ---------------------------------------------------------------------------

   Decode `bf` via huffman code

**/


char* debug_huff_decode(struct bitfield* bf, struct huff_tree* t)
{
  return debug_huff_decode_helper(bf,t->root);
}



/**

   Function: void debug_print_uuid(struct uuid* uuid)
   --------------------------------------------------

**/

void debug_print_uuid(struct uuid* uuid)
{
  printf("%8.8x-%4.4x-%2.2x-%2.2x",uuid->sec,uuid->msec,uuid->seq,uuid->node_rand);
  return;
}

/**

   Function: void debug_print_file(struct file* file)
   --------------------------------------------------

**/


void debug_print_file(struct file* file)
{
  struct chunk* c;

  debug_print_bitfield(file->name);
  printf(" : ");
  
  c=file->chunks;
  while(c)
    {
      debug_print_uuid(c->uuid);
      printf(" ");
      c=c->next;
    }

  return;

}
